#!/usr/bin/env python
# -*- coding: utf-8 -*-
# @author: Florian Dorn <florian.dorn@gmail.com>
# @package: agenda
# @license: GNU GPLv2
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.


try:
	from xml.etree import ElementTree
except ImportError:
	from elementtree import ElementTree

import gdata.calendar.service
#import gdata.service
#import atom.service
import gdata.calendar
import atom
import traceback
import urllib

import datetime

#import dateutil.parser

### this url returns the task list
### https://www.google.com/calendar/tdl?secid=aw1463CRDYlZ6kAZTbmo7CwcSlw&tdl=%7B%22action_list%22%3A%5B%7B%22action_type%22%3A%22get_all%22%2C%22action_id%22%3A%221%22%2C%22list_id%22%3A%2204826080249802950676%3A0%3A0%22%2C%22get_deleted%22%3Afalse%7D%5D%2C%22client_version%22%3A-1%7D
###

#Import the Base class of all Providers
from agenda.CalendarProviderBase import CalendarProviderBase
from agenda.Config import Password
from gettext import gettext as _
from agenda.appointment import *
from agenda import dumpObj
class GoogleCalendar(CalendarProviderBase):
	"""Provider for Accessing the google Canendar via the gData API"""
	#set the capability to provider
	capabilities = ['provider']
	
	config_defaults = {'username': '', 'password': Password('') }
	
	def __init__(self,shell = None):
		self.shell = shell
		"""
		Basic initialization of the Plugin
		you can set the pluginame, author, and a website
		"""
		#Don't forget to Call the CalendarProviderBase 'constructor'
		CalendarProviderBase.__init__(self)
		
		self.Plugin_Name = "Google Calendar"
		self.Plugin_Author = "Florian Dorn"
		
		self.options['username'] = ''
		self.options['password'] = ''
		
		self._has_config_widget = True
		
	def initPlugin(self, options, appointment):
		CalendarProviderBase.initPlugin(self,options)
		#initialitze gdata connection
		self.cal_client = gdata.calendar.service.CalendarService()
		self.cal_client.source = 'agenda'
		self.online = False;
		
		self.cal_client.email = self.options['username']
		self.cal_client.password = str(self.options['password'])
		self.appointment = appointment
	def read_events(self, master_update_calendar_flag = False):
		#TODO: uncomment!
		cals = self.list_calendars()
		#cals = cals[:2]
		for calendar in cals:
			try:
				print calendar
				update_calendar_flag = master_update_calendar_flag
				if(not update_calendar_flag):
					local_cal = self.appointment.get_calendar(calendar.id)
					if(local_cal != None):
						#print "Comparing local and remote updated_ext times:"
						#print "%s   %s - %s" % ( local_cal.id, local_cal.updated_ext, calendar.updated_ext )
						update_calendar_flag = (local_cal.updated_ext != calendar.updated_ext)
						local_cal.updated_ext = calendar.updated_ext
						calendar = local_cal
					else:
						update_calendar_flag = True
				print "update_calendar_flag:", update_calendar_flag
				if(update_calendar_flag):
					projection = 'full'
				
					period = self.appointment.get_period()
					query = gdata.calendar.service.CalendarEventQuery(calendar.id, 'private',projection)
					query.start_min = (datetime.datetime.utcnow() + period.get_start()).strftime('%Y-%m-%d')
					query.start_max = (datetime.datetime.utcnow() + period.get_end()).strftime('%Y-%m-%d')
					query.orderby = 'starttime'
					query.sortorder = 'ascend'
					query.singleevents = 'true'
					
					try:
						self.add_calendar(calendar)
						self.queryCalendar(query,calendar)
						#only add the calendar all events were properly added
						#print "todo: add calendar %s" % calendar
					
						pass
					except Exception,e:
						traceback.print_exc()
						self.notifyError(_("Could not retrieve Calendar '%s'") % calendar)
			except Exception,e:
				traceback.print_exc()
	
		return self.update_ok
	def queryCalendar(self,query,cal):
		#print cal
		#print query
		Emit(cal,'updating-started')
		feed = self.cal_client.CalendarQuery(query)
		cal_name = feed.title.text
		for i, an_event in enumerate(feed.entry):
			try:
				self.add_single_event_local(an_event,cal)
			except Exception,e:
				print "could not add event"
				print event
				traceback.print_exc()
		Emit(cal, 'updating-finished')
	def add_single_event_local(self,an_event,calendar):
			title = an_event.title.text
			if (title == None):
				title = _("(untitled)")
			for i,a_when in enumerate(an_event.when):
				start_time 	= (convert_datetime(a_when.start_time))
				end_time 	= (convert_datetime(a_when.end_time))
				place = u''
				for a in an_event.where:
					place = a.value_string
				try:
					descr = ['',an_event.content.text][an_event.content.text != None]
				except:
					descr = ''
				if(an_event.event_status.value != "CANCELED"):
					event = CalEvent(	an_event.id.text,
										calendar,
										start_time,
										end_time,
										title,
										descr,
										place,
										an_event.event_status.value
										)
					self.add_event(event)
				#else:
				#	print "skipping CANCELED event %s" % an_event.title.text		
	def login(self):
		if self.online:
			return
		try:
			self.cal_client.ProgrammaticLogin()
			feed = self.cal_client.GetAllCalendarsFeed()
			self.online = True
		except Exception,e:
			self.online = False
			print e
			self.notifyError(_("Could not contact the Google Calendar Server:\n%s") % e)
			self.update_ok = False
	def list_calendars(self):
		""" return a list of the calendars """
		import pprint
		self.login()
		calendars = []
				##grab all calendars
		feed = self.cal_client.GetAllCalendarsFeed()
		if(self.online and feed):
			self.update_ok = True
			for i, a_calendar in enumerate(feed.entry):
					visible = True
					try:
						access_level = a_calendar.access_level.value
					except:
						access_level = "read"
					if (a_calendar.hidden.value == "true") or (a_calendar.selected.value == "false"):
						visible = False
					id = urllib.unquote(a_calendar.id.text[a_calendar.id.text.rfind('/')+1:])
					title = a_calendar.title.text
					override = None
					for ext in a_calendar.extension_elements:
						if ext.tag == "overridename":
							title = ext.attributes["value"]
							pass
					color = a_calendar.color.value
					updated = local2utc(convert_datetime(a_calendar.updated.text))
					
					cal = CalCalendar(id,title,color,updated,self,visible,access_level)
					calendars.append(cal)
		return calendars
	def getSettingsPanel(self):
		"""return a gtk Widget showind the settings"""
		return gtk.Label(_("No configuration needed"))
	def applySettings(self):
		"""apply the changes to self.options made to the widgets"""
	def config_change_cb(self,appointments,path,value):
		#print "config_change_cb %s: %s" % (path,value)
		if(path == "plugins/GoogleCalendar/username"):
			self.cal_client.email = value
		elif (path == "plugins/GoogleCalendar/password"):
			self.cal_client.password = value
	def create_event(self,calendar, what="new Event",start_time=None,end_time=None,where="",description="",recurrence_data=None):
		
		"""
		create an event.
		start_time and end_time are datetime objects without TZinfo, which is interpreted as GMT
		recurrence data follows the iCalendar standard (RFC 2445 http://www.ietf.org/rfc/rfc2445.txt)
		"""
		#if recurrence_data is None:
		#  recurrence_data = ('DTSTART;VALUE=DATE:20070501\r\n'
		#+ 'DTEND;VALUE=DATE:20070502\r\n'
		#+ 'RRULE:FREQ=WEEKLY;BYDAY=Tu;UNTIL=20070904\r\n')
		
		#create the event
		event = gdata.calendar.CalendarEventEntry()
		#and fill in the arguments
		event.title = atom.Title(text=what)
		event.content = atom.Content(text=description)
		event.where.append(gdata.calendar.Where(value_string=where))

		start_time = start_time.strftime('%Y-%m-%dT%H:%M:%S.000Z')
		end_time = end_time.strftime('%Y-%m-%dT%H:%M:%S.000Z')

		event.when.append(gdata.calendar.When(start_time=start_time, end_time=end_time))

		# Set a recurring event
		if recurrence_data:
			event.recurrence = gdata.calendar.Recurrence(text=recurrence_data)
#		try:
		self.login()
		if self.online:
			cal_id = "/calendar/feeds/%s/private/full" % calendar.id
			new_event = self.cal_client.InsertEvent(event, cal_id)
		else:
			raise Exception("Could not log in")

		print 'New event inserted: %s' % (new_event.id.text,)
		print '\tEvent edit URL: %s' % (new_event.GetEditLink().href,)
		print '\tEvent HTML URL: %s' % (new_event.GetHtmlLink().href,)
		
		self.add_single_event_local(new_event,calendar)

		pass
	
	def get_config_widget(self):
		"""
		return the configuration widget
		"""
		return None
